package com.baba.bracelet.controller;

import com.alibaba.fastjson.JSONObject;
import com.baba.bracelet.base.BaseApiService;
import com.baba.bracelet.base.BaseResponse;
import com.baba.bracelet.constants.Constants;
import com.baba.bracelet.entity.*;
import com.baba.bracelet.service.*;
import com.baba.bracelet.token.GenerateToken;
import com.baba.bracelet.utils.BabaBeanUtils;
import com.baba.bracelet.utils.DateUtils;
import com.baba.bracelet.utils.OkHttpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sun.org.apache.xpath.internal.operations.Bool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wulongbo
 * @version 1.0
 * @date 2020/6/10 17:32
 * @description
 */
@RestController
@RequestMapping("/upstream")
@CrossOrigin
@Api(tags = "终端主动发起（设备-->服务器）模块")
public class UpController extends BaseApiService<JSONObject> {

    @Autowired
    private EquipService equipService;

    @Autowired
    private GenerateToken generateToken;

    @Autowired
    private CallRecordService callRecordService;

    @Autowired
    private VoiceService voiceService;

    @Autowired
    private RateService rateService;

    @Autowired
    private RateHistoryService rateHistoryService;

    @Autowired
    private UERelationService ueRelationService;

    @Autowired
    private SportService sportService;

    @Autowired
    private PressureService pressureService;

    @Autowired
    private PressureHistoryService pressureHistoryService;

    @Autowired
    private SleepService sleepService;

    @Autowired
    private VersionService versionService;

    @Autowired
    private SleepHistoryService sleepHistoryService;

    @Autowired
    private PictureService pictureService;

    @Autowired
    private VideoService videoService;

    @Autowired
    private EquipInfoService equipInfoService;

    @Autowired
    private EquipStateService equipStateService;

    private Boolean getToken(String token){
        String imsi=generateToken.getToken(token);
        if(StringUtils.isNotBlank(imsi)){
            return true;
        }
        return false;
    }


    @ApiOperation(value="设备注册", notes="设备注册")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "imei", dataType = "String", required = true, value = "设备IMEI号"),
            @ApiImplicitParam(paramType = "query", name = "imsi", dataType = "String", required = true, value = "设备imsi"),
            @ApiImplicitParam(paramType = "query", name = "factory", dataType = "String", required = true, value = "厂商标识"),
            @ApiImplicitParam(paramType = "query", name = "type", dataType = "String", required = true, value = "设备型号"),
            @ApiImplicitParam(paramType = "query", name = "operator", dataType = "String", required = true, value = "运营商")})
    @RequestMapping("/register")
    public BaseResponse<JSONObject> register(String imei,String imsi,String factory,String type,String operator) throws IOException {

        if(StringUtils.isEmpty(imei)){
            return setResultError("设备IMEI号不能为空！");
        }
        if(StringUtils.isEmpty(imsi)){
            return setResultError("设备imsi不能为空！");
        }
        if(StringUtils.isEmpty(factory)){
            return setResultError("厂商标识不能为空！");
        }
        if(StringUtils.isEmpty(type)){
            return setResultError("设备型号不能为空！");
        }
        if(StringUtils.isEmpty(operator)){
            return setResultError("运营商不能为空！");
        }
        if(!StringUtils.equals(factory, Constants.FACTORY)){
            return setResultError("厂商标识不正确！");
        }

        // 5.根据设备IMEI号 + 设备型号 查询当前注册设备之前是否注册过，
        EquipEntity entity= equipService.getOne(Wrappers.<EquipEntity>lambdaQuery().eq(EquipEntity::getImei,imei).eq(EquipEntity::getType,type));
        if(entity==null){
            EquipEntity equipEntity=new EquipEntity();
            equipEntity.setImei(imei);
            equipEntity.setImsi(imsi);
            equipEntity.setFactory(factory);
            equipEntity.setType(type);
            equipEntity.setOperator(operator);
            equipEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));
            Boolean result=equipService.save(equipEntity);
            if(!result){
                return setResultError("设备注册失败，请联系后台管理员Bob");
            }
        }

        // 6.生成对应设备令牌存放在redis中
        String keyPrefix=Constants.EQUIP_TOKEN_KEYPREFIX+type;
        String token=generateToken.createToken(keyPrefix,imei + "");

        JSONObject data=new JSONObject();
        data.put("token",token);
        return setResultSuccess(data);
    }

    private String getIMEI(String token){
        String imei=generateToken.getToken(token);
        if(StringUtils.isEmpty(imei)){
            return null;
        }
        return imei;
    }


    @ApiOperation(value="双向通话 （第三方呼叫使用）", notes="双向通话 （第三方呼叫使用）")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "imsi", dataType = "String", required = true, value = "设备imsi"),
            @ApiImplicitParam(paramType = "query", name = "cNumber", dataType = "String", required = true, value = "被叫号码"),
            @ApiImplicitParam(paramType = "query", name = "talkTime", dataType = "int", required = true, value = "通话时长"),
            @ApiImplicitParam(paramType = "query", name = "createTime", dataType = "String", required = true, value = "通话开始时间"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/twoWayCall")
    public BaseResponse<JSONObject> twoWayCall(String imsi,String cNumber,int talkTime,String createTime,String token) throws IOException {
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        CallRecordEntity callRecordEntity=new CallRecordEntity();
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        callRecordEntity.setImei(imei);
        callRecordEntity.setImsi(imsi);
        callRecordEntity.setCallNum(cNumber);
        callRecordEntity.setCreateTime(DateUtils.parseDate(createTime));
        callRecordEntity.setTalkTime(talkTime);
        Boolean result=callRecordService.save(callRecordEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }


    @ApiOperation(value="语音查询接收协议", notes="语音查询接收协议")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "url", dataType = "String", required = true, value = "语音包地址"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/voice")
    public BaseResponse<JSONObject> voice(String url,String token) throws IOException {
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        VoiceEntity voiceEntity=new VoiceEntity();
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        voiceEntity.setImei(imei);
        voiceEntity.setUrl(url);
        voiceEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));
        Boolean result=voiceService.save(voiceEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }

    private BaseResponse<JSONObject> isBind(String imei,String token){
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        UERelationEntity ueRelationEntity=ueRelationService.getOne(Wrappers.<UERelationEntity>lambdaQuery().eq(UERelationEntity::getEquipId,imei));
        if(ueRelationEntity==null){
            return setResultError(407,"设备未进行绑定，请先绑定设备！");
        }
        Integer isBind=ueRelationEntity.getIsBind();
        if(isBind==0){
            return setResultError(407,"设备已解绑，请先绑定设备！");
        }
        String userId=ueRelationEntity.getUserId();
        if(StringUtils.isEmpty(userId)){
            return setResultError(406,"用户设备信息关联有误！");
        }
        return setResultSuccess(userId);
    }

    @ApiOperation(value="心率数据上传", notes="心率数据上传")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "rate", dataType = "String", required = true, value = "心率"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/rate")
    public BaseResponse<JSONObject> rate(String rate,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        BaseResponse<JSONObject> json= isBind(imei,token);
        if(json.getCode()!=200){
         return json;
        }
        /**
         * 移入历史心率表，并删除当前心率表数据
         */
        RateEntity hisRate=rateService.getOne(Wrappers.<RateEntity>lambdaQuery().eq(RateEntity::getUserId,json.getMsg()));
        if(hisRate!=null){
            Boolean insert=rateHistoryService.save(BabaBeanUtils.voToDto(hisRate,RateHistoryEntity.class));
            if(!insert){
                // 插入失败
                return setResultError(405,"移表操作失败！请联系后台管理员Bob");
            }
            // 插入成功，删除心率表数据
            Boolean delete=rateService.removeById(hisRate.getId());
            if(!delete){
                // 删除失败
                return setResultError(405,"删表操作失败！请联系后台管理员Bob");
            }
        }
        // 首次上报心率数据  or  删除成功，插入新数据
        RateEntity rateEntity=new RateEntity();
        rateEntity.setUserId(json.getMsg());
        rateEntity.setRate(rate);
        rateEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));
        Boolean result=rateService.save(rateEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }


    @ApiOperation(value="血压数据上传", notes="血压数据上传")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "systolic", dataType = "int", required = true, value = "血压高压 [收缩压]"),
            @ApiImplicitParam(paramType = "query", name = "diastolic", dataType = "int", required = true, value = "血压低压 [舒张压]"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/pressure")
    public BaseResponse<JSONObject> pressure(Integer systolic,Integer diastolic,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        BaseResponse<JSONObject> json= isBind(imei,token);
        if(json.getCode()!=200){
            return json;
        }

        /**
         * 移入历史心率表，并删除当前心率表数据
         */
        PressureEntity hisPressure=pressureService.getOne(Wrappers.<PressureEntity>lambdaQuery().eq(PressureEntity::getUserId,json.getMsg()));
        if(hisPressure!=null){
            Boolean insert=pressureHistoryService.save(BabaBeanUtils.voToDto(hisPressure,PressureHistoryEntity.class));
            if(!insert){
                // 插入失败
                return setResultError(405,"移表操作失败！请联系后台管理员Bob");
            }
            // 插入成功，删除血压表数据
            Boolean delete=pressureService.removeById(hisPressure.getId());
            if(!delete){
                // 删除失败
                return setResultError(405,"删表操作失败！请联系后台管理员Bob");
            }
        }

        // 首次上报血压数据  or  删除成功，插入新数据
        PressureEntity pressureEntity=new PressureEntity();
        pressureEntity.setUserId(json.getMsg());
        pressureEntity.setSystolic(systolic);
        pressureEntity.setDiastolic(diastolic);
        pressureEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));
        Boolean result=pressureService.save(pressureEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }


    @ApiOperation(value="睡眠质量", notes="睡眠质量")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "space", dataType = "int", required = true, value = "30: 表示按30s 统计一次"),
            @ApiImplicitParam(paramType = "query", name = "start", dataType = "String", required = true, value = "睡眠开始时间 "),
            @ApiImplicitParam(paramType = "query", name = "end", dataType = "String", required = true, value = "睡眠结束时间 "),
            @ApiImplicitParam(paramType = "query", name = "quality", dataType = "int", required = true, value = "睡眠质量(0：差/1：良好/2：优)"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/sleep")
    public BaseResponse<JSONObject> sleep( Integer space, String start,String end,Integer quality, String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        BaseResponse<JSONObject> json= isBind(imei,token);
        if(json.getCode()!=200){
            return json;
        }

        /**
         * 移入睡眠质量表，并删除当前睡眠质量表数据
         */
        SleepEntity hisSleep=sleepService.getOne(Wrappers.<SleepEntity>lambdaQuery().eq(SleepEntity::getUserId,json.getMsg()));
        if(hisSleep!=null){
            Boolean insert=sleepHistoryService.save(BabaBeanUtils.voToDto(hisSleep,SleepHistoryEntity.class));
            if(!insert){
                // 插入失败
                return setResultError(405,"移表操作失败！请联系后台管理员Bob");
            }
            // 插入成功，删除血压表数据
            Boolean delete=sleepService.removeById(hisSleep.getId());
            if(!delete){
                // 删除失败
                return setResultError(405,"删表操作失败！请联系后台管理员Bob");
            }
        }
        // 首次上报血压数据  or  删除成功，插入新数据
        SleepEntity sleepEntity=new SleepEntity();
        sleepEntity.setUserId(json.getMsg());
        sleepEntity.setSpace(space);
        sleepEntity.setStart(new Timestamp(DateUtils.parseDate(start).getTime()));
        sleepEntity.setEnd(new Timestamp(DateUtils.parseDate(end).getTime()));
        sleepEntity.setQuality(quality);
        sleepEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));
        Boolean result=sleepService.save(sleepEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }


    @ApiOperation(value="步数上报", notes="步数上报")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "total", dataType = "int", required = true, value = "运动时长(s)"),
            @ApiImplicitParam(paramType = "query", name = "distance", dataType = "int", required = true, value = "运动总距离(m)"),
            @ApiImplicitParam(paramType = "query", name = "step", dataType = "int", required = true, value = "运动总步数"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/sport")
    public BaseResponse<JSONObject> sport(Integer total,Integer distance,Integer step,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        BaseResponse<JSONObject> json= isBind(imei,token);
        if(json.getCode()!=200){
            return json;
        }
        SportEntity sportEntity=new SportEntity();
        sportEntity.setUserId(json.getMsg());
        sportEntity.setDistance(distance);
        sportEntity.setStep(step);
        sportEntity.setTotal(total);
        sportEntity.setCreateTime(DateUtils.parseDate(DateUtils.getDateTime()));//数据上传时间
        Boolean result=sportService.save(sportEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }

    @ApiOperation(value="设备上行版本信息", notes="设备上行版本信息")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/version")
    public BaseResponse<JSONObject> version(String token) throws IOException {
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        VersionEntity versionEntity=versionService.getOne(Wrappers.<VersionEntity>lambdaQuery().eq(VersionEntity::getVersionInUse,1));
        if(versionEntity==null){
            return setResultError(501,"服务器没有设备可用版本信息，请先在服务器更新设备版本信息！");
        }
        versionEntity.setCreateTime(versionEntity.getCreateTime());
        JSONObject data=new JSONObject();
        data.put("version",versionEntity);
        return setResultSuccess(data);
    }

    @ApiOperation(value="图片上传", notes="图片上传")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "url", dataType = "String", required = true, value = "图片地址"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/picture")
    public BaseResponse<JSONObject> picture(String url,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        if(StringUtils.isEmpty(imei)){
            return setResultError("设备IMEI号不能为空！");
        }
        if(StringUtils.isEmpty(url)){
            return setResultError("图片地址不能为空！");
        }
        PictureEntity pictureEntity=new PictureEntity();
        pictureEntity.setImei(imei);
        pictureEntity.setUrl(url);
        pictureEntity.setCreateTime((DateUtils.parseDate(DateUtils.getDateTime())));;//数据上传时间
        Boolean result=pictureService.save(pictureEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }

    @ApiOperation(value="视频上传", notes="视频上传")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "url", dataType = "String", required = true, value = "视频地址"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/video")
    public BaseResponse<JSONObject> video(String url,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        if(StringUtils.isEmpty(imei)){
            return setResultError("设备IMEI号不能为空！");
        }
        if(StringUtils.isEmpty(url)){
            return setResultError("视频地址不能为空！");
        }
        VideoEntity videoEntity=new VideoEntity();
        videoEntity.setImei(imei);
        videoEntity.setUrl(url);
        videoEntity.setCreateTime((DateUtils.parseDate(DateUtils.getDateTime())));;//数据上传时间
        Boolean result=videoService.save(videoEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }

    @ApiOperation(value="定位数据，GPS+LBS+状态+基站+WIFI+报警", notes="定位数据，GPS+LBS+状态+基站+WIFI+报警")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "lat", dataType = "String", required = true, value = "纬度"),
            @ApiImplicitParam(paramType = "query", name = "lon", dataType = "String", required = true, value = "经度"),
            @ApiImplicitParam(paramType = "query", name = "address", dataType = "String", required = true, value = "详细地址信息"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/location")
    public BaseResponse<JSONObject> location(String lat,String lon,String address,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        if(StringUtils.isEmpty(imei)){
            return setResultError("设备IMEI号不能为空！");
        }
        if(StringUtils.isEmpty(lat)){
            return setResultError("地理位置纬度不能为空！");
        }
        if(StringUtils.isEmpty(lon)){
            return setResultError("地理位置经度不能为空！");
        }
        if(StringUtils.isEmpty(address)){
            return setResultError("详细地址信息不能为空！");
        }

        EquipInfoEntity equipInfoEntity=new EquipInfoEntity();
        equipInfoEntity.setImei(imei);
        equipInfoEntity.setLat(lat);
        equipInfoEntity.setLon(lon);
        equipInfoEntity.setAddress(address
        );
        equipInfoEntity.setCreateTime((DateUtils.parseDate(DateUtils.getDateTime())));;//数据上传时间
        Boolean result=equipInfoService.save(equipInfoEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }


    @ApiOperation(value="设备状态信息(电池电量+报警状态)", notes="设备状态信息(电池电量+报警状态)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "state", dataType = "int", required = false, value = "设备状态：00为无任何报警(01：SOS,02：低电,03：脱落报警,04:佩戴提醒，05：剪断报警,06:跌倒报警,07:心率异常, 08:心率过高, 09:心率过低,10收缩压过高,11收缩压过低,12舒张压过高,13舒张压过低)"),
            @ApiImplicitParam(paramType = "query", name = "battery", dataType = "int", required = false, value = "电池电量"),
            @ApiImplicitParam(paramType = "query", name = "token", dataType = "String", required = true, value = "令牌")})
    @RequestMapping("/state")
    public BaseResponse<JSONObject> state(Integer state,Integer battery,String token) throws IOException {
        String imei=getIMEI(token);
        if(StringUtils.isEmpty(imei)){
            return setResultError(502,"令牌失效，请重新登录！");
        }
        if(!getToken(token)){
            return setResultError(408,"设备认证失败，请重新登录或更换设备！");
        }
        if(StringUtils.isEmpty(imei)){
            return setResultError("设备IMEI号不能为空！");
        }
        EquipStateEntity equipStateEntity=new EquipStateEntity();
        equipStateEntity.setImei(imei);
        equipStateEntity.setBattery(battery);
        equipStateEntity.setState(state);
        Boolean result=equipStateService.saveOrUpdate(equipStateEntity);
        if(!result){
            return setResultError("系统错误！");
        }
        return setResultSuccess();
    }

}
